#include "sgame.h"

snake_t players[MAX_PLAYERS];
uint8_t is_alive[MAX_PLAYERS];
uint16_t alive_snakes;
FILE* log_file;
node_t *fruit_list;
node_t *last_list;



static uint8_t prev_dir[MAX_PLAYERS];

extern uint16_t num_clients;
extern FILE* log_file;

void gen_snakes(uint16_t field_x, uint16_t field_y)
{
    fprintf(log_file, "Creating %d snakes...\n", num_clients);
    if (field_y * 2 < num_clients || field_x < 20)
    {
        fprintf(stderr, "The field too small !\n");
        exit(EXIT_FAILURE);
    }

    for (size_t i = 0; i < num_clients; i++){
        fprintf(log_file, "Snake %zu created in:\n", i);
        for (size_t j = 0; j < SNAKE_SIZE; j++){
            players[i].body[j].x = 10 + j;
            players[i].body[j].y = i*2 + 1;
            players[i].dir = MOVE_LEFT;
            players[i].len = SNAKE_SIZE;
            fprintf(log_file, "\tx%zu:%lu y%zu:%lu\n", i, 4+j, i, i*2);
        }
    }
    
    alive_snakes = num_clients;
    memset(is_alive, 1, MAX_PLAYERS);
    fprintf(log_file, "\n");
}


void change_crd(uint16_t num)
{
    uint16_t head_x, head_y;
    
    fprintf(log_file, "Snake %d change dir: %d\n", num, players[num].dir);

    head_x = players[num].body[0].x;
    head_y = players[num].body[0].y;

    if (players[num].dir == MOVE_UP && prev_dir[num] == MOVE_DOWN)
        players[num].dir = MOVE_DOWN;
    else if (players[num].dir == MOVE_DOWN && prev_dir[num] == MOVE_UP)
        players[num].dir = MOVE_UP;
    else if (players[num].dir == MOVE_LEFT && prev_dir[num] == MOVE_RIGHT)
        players[num].dir = MOVE_RIGHT;
    else if (players[num].dir == MOVE_RIGHT && prev_dir[num] == MOVE_LEFT)
        players[num].dir = MOVE_LEFT;

    switch(players[num].dir)
    {
        case MOVE_DOWN:
            players[num].body[0].y += 1;
            break;

        case MOVE_UP:
            players[num].body[0].y -= 1;
            break;

        case MOVE_LEFT:
            players[num].body[0].x -= 1;
            break;

        case MOVE_RIGHT:
            players[num].body[0].x += 1;
            break;
    }

    uint16_t tmp_x, tmp_y;
    fprintf(log_file, "0. x: %d, y: %d\n", players[num].body[0].x,
                                players[num].body[0].y);
    for (int i = 1; i < players[num].len; ++i)
    {
        tmp_x = players[num].body[i].x;
        tmp_y = players[num].body[i].y;
        
        fprintf(log_file, "%d. x: %d, y: %d\n", i, tmp_x, tmp_y);

        players[num].body[i].x = head_x;
        players[num].body[i].y = head_y;
        
        head_x = tmp_x;
        head_y = tmp_y;
    }

    prev_dir[num] = players[num].dir;
}


void change_crd_snakes()
{
    for (int i = 0; i < num_clients; ++i)
    {
        if (is_alive[i] != 1)
            continue;

        change_crd(i);
    }
}


int check_dead(uint16_t num, uint16_t fx, uint16_t fy)
{
    if (!is_alive[num]) return 0;

    if (alive_snakes == 1 && num_clients > 1)
        return 1;

    for (int i = 0; i < num_clients; ++i)
    {
        if (!is_alive[i]) continue;
        
        int b = 0;

        //sama sebya
        if (i == num)
            b = 1;
        
        //ob drugih zmei
        for (; b < players[i].len; ++b)
        {
            if (players[num].body[0].x == players[i].body[b].x &&
                    players[num].body[0].y == players[i].body[b].y)
                return 1;
        }
    }

    if (players[num].body[0].x == 0 ||
            players[num].body[0].y == 0)
        return 1;

    if (players[num].body[0].x == fx-1 || 
            players[num].body[0].y == fy-1)
        return 1;

    return 0;
}


int check_eat(uint16_t num)
{
    node_t *list = fruit_list;

    if (!is_alive[num]) return 0;

    while (list != NULL)
    {
        fprintf(log_file, "FRUIT. X: %d Y: %d\n", ((crd_t *)(list->data))->x, ((crd_t *)(list->data))->y);
        if (players[num].body[0].x == ((crd_t *)(list->data))->x &&
                players[num].body[0].y == ((crd_t *)(list->data))->y)
        {
            players[num].len += 1;
            delete_node(list, &fruit_list, &last_list);
            return 1;
        }

        list = list->next;
    }

    return 0;
}


void spawn_fruit(uint16_t fx, uint16_t fy)
{

    long rnd;
    crd_t *crd = malloc(sizeof(crd_t));
    if (fruit_list == NULL)
    {
        fruit_list = malloc(sizeof(node_t));   
        
        rnd = random();
        crd->x = ((rnd % fx) - 2 > 0) ? (rnd % fx) - 2 : 1;
        
        rnd = random();
        crd->y = ((rnd % fy) - 2 > 0) ? (rnd % fy) - 2 : 1;

        fruit_list->data = crd;
        fruit_list->prev = NULL;
        fruit_list->next = NULL;

        last_list = fruit_list;

        return;
    }
    
    crd = malloc(sizeof(crd_t));

    rnd = random();
    crd->x = ((rnd % fx) - 1 > 0) ? (rnd % fx) - 1 : 1;
    
    rnd = random();
    crd->y = ((rnd % fy) - 1 > 0) ? (rnd % fy) - 1 : 1;

    last_list = insert_node(last_list, crd);
}
